#include <iostream>
using namespace std;
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

//1.阻塞IO

/* int main(){
    char buffer[1024] = {0};
    while(1){
        ssize_t n = read(0, buffer, sizeof(buffer)); //0就是stdin，即键盘
        if(n < 0){
            cout << "read error" << endl;
            exit(-1);
        }
        else{
            buffer[n - 1] = 0;
            cout << buffer << endl;
        }
    }
    return 0;
} */




//2.非阻塞IO

void SetNoBlock(int fd) {
	//1.先通过cmd(F_GETFL)获取到当前的同步/异步IO状态
	int fl = fcntl(fd, F_GETFL);
	//2.获取失败直接返回
	if (fl < 0) {
		perror("fcntl");
		return;
	}
	//3.成功后，重新进行设置，使用F_SETFL进行设置
	//设置的方法就是把需要的选项按位或起来，open的选项操作也是这样的！
	fcntl(fd, F_SETFL, fl | O_NONBLOCK);
}

int main(){
    //设置stdin非阻塞
    SetNoBlock(0);

    char buffer[1024] = {0};
    while(1){
        ssize_t n = read(0, buffer, sizeof(buffer)); //0就是stdin，即键盘
        if(n > 0){
            buffer[n - 1] = 0;
            cout << buffer << endl;
        }
        //按下ctrl + d，退出从标准输入的读取！
        else if(n == 0){
            break;
        }
        // n < 0
        else{
            //这里需要说的是：n < 0，一定代表读取出错吗？
            //如果在阻塞那里肯定是了！
            //但是现在时非阻塞！ -> 有两种可能不是出错的： 
            // 1.条件未就绪
            // 2.因为信号而退出读写
            
            //怎么判断？
            //我们可以发现，read返回值中，如果是出错了，会设置错误码到errno中！
            //所以我们通过查看错误码就知道是什么情况了！

            //1.条件未就绪：
            if(errno == EAGAIN || errno == EWOULDBLOCK){
                cout << "条件未就绪！" << endl;
                sleep(1);
                continue;
            }

            //2.被信号中断了
            else if(errno == EINTR){
                sleep(1);
                continue;
            }

            else{
                //这是真正的出错！ 直接退出
                exit(-1);
            }
        }

        //这里打印一下 -> 如果说是非阻塞，这里是始终被打印的！
        cout << "非阻塞的打印" << endl;
    }
    return 0;
}